package com.noahedus.desktopclick.game.net;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by lenovo on 2019/11/8.
 * 接口实现类
 * 采用Okhttp进行网络请求
 */

public class OkhttpNetManager implements INetManager {

    private static OkHttpClient sokHttpClient;

    //主线程的handler
    private static Handler shandler = new Handler(Looper.getMainLooper());


    static {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        //设置请求时间
        builder.connectTimeout(15, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS);
        sokHttpClient = builder.build();
    }

    @Override
    public void get(String url, final INetGetCallBack callback, Object tag) {
        final Request.Builder builder = new Request.Builder();
        Request request = builder.url(url).get().tag(tag).build();
        Call call = sokHttpClient.newCall(request);
//        Response execute = call.execute();//同步操作
        //异步操作
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                if (call.isCanceled()) {
                    return;
                }
                //非ui线程
                shandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //ui线程
                        callback.failed(e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                try {
                    if (call.isCanceled()) {
                        return;
                    }
                    final String string = response.body().string();
                    //非ui线程
                    shandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //ui线程
                            callback.success(string);
                        }
                    });
                } catch (Throwable e) {
                    e.printStackTrace();
                    callback.failed(e);
                }
            }
        });
    }

    @Override
    public void post(String url, Map<String, String> headersParams, Map<String, String> params, final INetPostCallBack callback, Object tag) {
        Request.Builder builder1 = new Request.Builder().url(url);
        if (headersParams != null) {//遍历head参数
            for (Map.Entry<String, String> entry : headersParams.entrySet()) {
                builder1 = builder1.addHeader(entry.getKey(), entry.getValue());
            }
        }
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null) {//遍历参数
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder = builder.add(entry.getKey(), entry.getValue());
            }
        }

        FormBody body = builder.build();
        Request request = builder1.post(body).tag(tag).build();
        Call call = sokHttpClient.newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(final Call call, final IOException e) {
                if (call.isCanceled()) {
                    return;
                }
                //非ui线程
                shandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //ui线程
                        callback.failed(e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    if (call.isCanceled()) {
                        return;
                    }
                    final String string = response.body().string();
                    //非ui线程
                    shandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //ui线程
                            callback.success(string);
                        }
                    });
                } catch (Throwable e) {
                    e.printStackTrace();
                    callback.failed(e);
                }
            }
        });

    }


    @Override
    public void postFile(String url, String fileKey, File file, Map<String, String> params, final INetPostFileCallBack callback, Object tag) {
        if (!file.exists()) {
            //文件不存在
            Log.d("print", "postFile: 要上传的文件不存在");
            return;
        }
        // form 表单形式上传
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        // MediaType.parse() 里面是上传的文件类型。不清楚的可以写application/octet-stream
        //图片的类型就可以写image/*这种
        RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        // 参数分别为， 请求key ，文件名称 ， RequestBody
        builder.addFormDataPart(fileKey, file.getName(), body);
        if (params != null) {
            // map 里面是请求中所需要的 key 和 value
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.addFormDataPart(entry.getKey(), entry.getValue());
            }
        }
        MultipartBody multipartBody = builder.build();
        Request request = new Request.Builder().url(url).post(multipartBody).tag(tag).build();
        sokHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                if (call.isCanceled()) {
                    return;
                }
                //非ui线程
                shandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //ui线程
                        callback.failed(e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    if (call.isCanceled()) {
                        return;
                    }
                    final String string = response.body().string();
                    //非ui线程
                    shandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //ui线程
                            callback.success(string);
                        }
                    });
                } catch (Throwable e) {
                    e.printStackTrace();
                    callback.failed(e);
                }
            }
        });


    }

    @Override
    public void downFile(String url, final File file,
                         final INetDownFileCallBack callback, Object tag) {
        if (!file.exists()) {//如果文件不存在，先创建路径
            file.getParentFile().mkdirs();
        }
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(url).get().tag(tag).build();
        Call call = sokHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                if (call.isCanceled()) {
                    return;
                }
                //非ui线程
                shandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //ui线程
                        callback.failed(e);
                    }
                });

            }

            @Override
            public void onResponse(final Call call, Response response) throws IOException {
                InputStream is = null;
                OutputStream os = null;

                try {

                    final long totalLen = response.body().contentLength();

                    is = response.body().byteStream();
                    os = new FileOutputStream(file);

                    byte[] buffer = new byte[8 * 1024];
                    long curLen = 0;
                    int bufferLen = 0;
                    while (!call.isCanceled() && (bufferLen = is.read(buffer)) != -1) {
                        os.write(buffer, 0, bufferLen);
                        os.flush();
                        curLen += bufferLen;
                        final long finalCurLen = curLen;
                        shandler.post(new Runnable() {
                            @Override
                            public void run() {
                                //传递下载进度
                                callback.progress((int) (finalCurLen * 1.0f / totalLen * 100));
                            }
                        });
                    }
                    if (call.isCanceled()) {
                        return;
                    }
                    shandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.success(file);
                        }
                    });
                } catch (final Throwable e) {
                    if (call.isCanceled()) {
                        return;
                    }
                    //非ui线程
                    shandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //ui线程
                            callback.failed(e);
                        }
                    });
                } finally {
                    if (is != null) {
                        is.close();
                    }
                    if (os != null) {
                        os.close();
                    }
                }
            }
        });
    }


    @Override
    public void cancel(Object tag) {

        //正在排队的call
        List<Call> queuedCalls = sokHttpClient.dispatcher().queuedCalls();
        if (queuedCalls != null) {
            for (Call call : queuedCalls) {
                if (tag.equals(call.request().tag())) {
                    call.cancel();
                    Log.d("print", "取消的请求的tag: " + tag);
                }
            }
        }

        //正在运行的call
        List<Call> runningCalls = sokHttpClient.dispatcher().runningCalls();
        if (runningCalls != null) {
            for (Call call : runningCalls) {
                if (tag.equals(call.request().tag())) {
                    call.cancel();
                    Log.d("print", "取消的请求的tag: " + tag);
                }
            }
        }


    }


}
